package top.huahaizhi.zhihu.daily.util;

import android.content.Context;
import android.net.ConnectivityManager;
import android.util.Log;

import com.jakewharton.retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;

import java.io.IOException;

import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import okhttp3.Cache;
import okhttp3.CacheControl;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import top.huahaizhi.zhihu.daily.ApiService;
import top.huahaizhi.zhihu.daily.K;
import top.huahaizhi.zhihu.daily.bean.LatestNewsBean;
import top.huahaizhi.zhihu.daily.bean.StoryDetailBean;


/**
 * 海志 在 2017/8/3 0003 创建
 *
 * @mail huahaizhi@gmail.com
 * 功能：
 */

public class NetUtils {

    private static NetUtils utils;

    private Request request;
    private OkHttpClient okHttpClient;

    private Retrofit retrofit;

    private Context context;

    private NetUtils(Context context) {
        this.context = context;
        okHttpClient = new OkHttpClient.Builder().addInterceptor(getLogInterceptor()).addInterceptor(getUrlInterceptor(context)).cache(getCache(context)).build();
        retrofit = new Retrofit.Builder().baseUrl(K.BASE_URL).client(okHttpClient).addConverterFactory(GsonConverterFactory.create()).addCallAdapterFactory(RxJava2CallAdapterFactory.create()).build();
    }

    public static NetUtils getInstance(Context context) {
        if (utils == null) {
            synchronized (NetUtils.class) {
                if (utils == null)
                    utils = new NetUtils(context);
            }
        }
        return utils;
    }

    private static Cache getCache(Context context) {
        return new Cache(context.getCacheDir(), 400 * 1024 * 1024);
    }

    private static Interceptor getUrlInterceptor(final Context context) {
        return new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request request = chain.request();
                if (!isNetworkAvailable(context))
                    request = new Request.Builder().cacheControl(CacheControl.FORCE_CACHE).build();
                Response response = chain.proceed(request);
                String cacheControl = isNetworkAvailable(context) ? request.cacheControl().toString() : "public, only-if-cached, max-stale=120";
                return response.newBuilder()
                        .header("Cache-Control", cacheControl)
                        .build();
            }
        };
    }

    private static HttpLoggingInterceptor getLogInterceptor() {
        return new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
            @Override
            public void log(String message) {
                Log.e("RetrofitLog", "\n");
                Log.e("RetrofitLog", "\n");
                Log.e("RetrofitLog", "\n");
                Log.e("RetrofitLog", "##########################  ACCESS NET  #######################");
                Log.e("RetrofitLog", message);
                Log.e("RetrofitLog", "##########################  ACCESS NET  #######################");
                Log.e("RetrofitLog", "\n");
                Log.e("RetrofitLog", "\n");
                Log.e("RetrofitLog", "\n");
            }
        }).setLevel(HttpLoggingInterceptor.Level.BASIC);
    }

    public static boolean isNetworkAvailable(Context context) {
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        return (cm.getActiveNetworkInfo() != null);
    }

    private Observer getSimpleSubscriber(final OnRequestListener listener) {
        return new Observer() {
            @Override
            public void onSubscribe(Disposable d) {

            }

            @Override
            public void onNext(Object o) {
                if (listener != null)
                    listener.onSuccess(o);
            }

            @Override
            public void onError(Throwable t) {
                if (listener != null)
                    listener.onFail(t.getMessage());
            }


            @Override
            public void onComplete() {

            }
        };
    }

    private void toSubscribe(Observable o, Observer s) {
        o.subscribeOn(Schedulers.io())
                .unsubscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(s);
    }

    public interface OnRequestListener<T> {
        void onSuccess(T object);

        void onFail(String reason);
    }

    //##############################################################################################
    //########################    API 方法    ######################################################
    //##############################################################################################

    public void go(final String url, OnRequestListener<String> listener) {
        toSubscribe(new Observable<String>() {
            @Override
            protected void subscribeActual(Observer<? super String> observer) {
                try {
                    Response execute = okHttpClient.newCall(new Request.Builder().url(url).build()).execute();
                    ResponseBody body = execute.body();
                    int code = execute.code();

                    if (body != null&&code==200) {
                        observer.onNext(body.string());
                    } else {
                        observer.onError(new Exception("服务器错误（"+code+")"));
                    }
                    observer.onComplete();
                } catch (Exception e) {
                    observer.onError(e);
                }
            }
        }, getSimpleSubscriber(listener));
    }

    public void requestNews(OnRequestListener<LatestNewsBean> listener) {
        toSubscribe(retrofit.create(ApiService.class).latestNews(), getSimpleSubscriber(listener));
    }

    public void requestStoryDetail(OnRequestListener<StoryDetailBean> listener){
        toSubscribe(retrofit.create(ApiService.class).latestNews(), getSimpleSubscriber(listener));
    }
}
